/* Copyright (c) 2010-2020 Vadim Surov.
 */
package com.srv.client.widget;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.testing.MockEditorError;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.Text;
import com.google.gwt.xml.client.XMLParser;
import com.sencha.gxt.cell.core.client.form.TextAreaInputCell.Resizable;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
import com.sencha.gxt.widget.core.client.form.TextArea;
import com.sencha.gxt.widget.core.client.form.Validator;
import com.sencha.gxt.widget.core.client.toolbar.ToolBar;
import com.srv.shared.Card;
import com.srv.shared.Control;
import com.srv.shared.SetInfo;

public class SetSourcePanel extends VerticalLayoutContainer implements SetView {

	private ToolBar toolbar = new ToolBar();
	private TextArea source = new TextArea();
	private List<Card> cards;
	private boolean isSafeToClose = true;

	public static native void copyFrom(String text) /*-{
    $wnd.window.clipboardData.setData('text', text);
    }-*/;	

	public SetSourcePanel(final SetInfo setInfo, List<Card> cards) {
		super();

		toolbar.setSpacing(2);

		final TextButton copyAllButton = new TextButton("Copy All"){{
			addSelectHandler(new SelectHandler() {
				@Override
				public void onSelect(SelectEvent event) {
					copyFrom(source.getValue());
				}
			});
		}};
		toolbar.add(copyAllButton);

		add(toolbar, new VerticalLayoutData(1,-1));


		source.setHeight(500);
		source.setResizable(Resizable.BOTH);
		source.addValidator(new Validator<String>(){

			@SuppressWarnings("serial")
			@Override
			public List<EditorError> validate(Editor<String> editor,
					String value) {
				final String result = parse();
				if (result==null) { 
					isSafeToClose = true;
					return null;
				} else {
					isSafeToClose = false;
					return new ArrayList<EditorError>() {{ 
						add(new MockEditorError() { 
							@Override
							public String getMessage() {
								return result;
							}
						}); 
					}};
				}
			}
		});

		setCards(cards);		

		add(source, new VerticalLayoutData(1,1));	
	}

	public String parse() {

		if (source.getValue()==null) {
			return "There is nothing to apply";
		}

		try {
			Document doc = XMLParser.parse(source.getValue());

			int version = 1;

			NodeList atomyqNodelist = doc.getElementsByTagName("atomyq");
			if (atomyqNodelist.getLength()==1) {
				Element versionElement = (Element) atomyqNodelist.item(0);
				version = Integer.parseInt(versionElement.getAttribute("version"));
			}

			if (version == 2) {

				NodeList setNodelist = doc.getElementsByTagName("set");

				if (setNodelist.getLength()==1) {
					Element setElement = (Element) setNodelist.item(0);
					NodeList cardNodelist = setElement.getElementsByTagName("card");

					final List<Card> newCards = new LinkedList<Card>(); 

					for (int i=0, m=cardNodelist.getLength(); i<m; i++) {
						final Card card = new Card();
						Element cardElement = (Element) cardNodelist.item(i);
						//String cardName = cardElement.getAttribute("name");
						NodeList controlNodelist = cardElement.getElementsByTagName("control");
						List<Control> controlList = new LinkedList<Control>();
						for (int j=0, n=controlNodelist.getLength(); j<n; j++) {

							Element controlElement = (Element)controlNodelist.item(j);
							String controlName = controlElement.getAttribute("name");

							Control.Type controlType = Control.stringToTypeOld(controlName);
							String controlValue = controlName;

							if (controlName.equals("Text")) 
								controlValue = "";
							else if (controlName.equals("Image")) 
								controlValue = "";
							else if (controlName.equals("RadioOn")) 
								controlValue = "checked";
							else if (controlName.equals("RadioOff")) 
								controlValue = "unchecked";
							else if (controlName.equals("CheckboxOn")) 
								controlValue = "checked";
							else if (controlName.equals("CheckboxOff")) 
								controlValue = "unchecked";
							else if (controlName.equals("Line")) 
								controlValue = "";
							else if (controlName.equals("Score")) 
								controlValue = "";

							Text tt = (Text)controlElement.getFirstChild();
							String text = (tt==null)?"":tt.getData();
							controlList.add(new Control(controlType, controlValue, text));
						}
						card.setControls(controlList);
						newCards.add(card);
					}

					cards = newCards;

				} else {
					return "Set not found";
				}

			} else if (version == 3) {
				NodeList setNodelist = doc.getElementsByTagName("set");

				if (setNodelist.getLength()==1) {
					Element setElement = (Element) setNodelist.item(0);
					NodeList cardNodelist = setElement.getElementsByTagName("card");

					final List<Card> newCards = new LinkedList<Card>(); 

					for (int i=0, m=cardNodelist.getLength(); i<m; i++) {
						final Card card = new Card();
						Element cardElement = (Element) cardNodelist.item(i);
						//String cardName = cardElement.getAttribute("name");
						String floatingString = cardElement.getAttribute("floating");
						NodeList controlNodelist = cardElement.getElementsByTagName("control");
						List<Control> controlList = new LinkedList<Control>();
						for (int j=0, n=controlNodelist.getLength(); j<n; j++) {

							Element controlElement = (Element)controlNodelist.item(j);
							String controlType = controlElement.getAttribute("type");
							String controlValue = controlElement.getAttribute("value");
							Text tt = (Text)controlElement.getFirstChild();
							String text = (tt==null)?"":tt.getData();
							controlList.add(new Control(controlType, controlValue, text));
						}
						card.setFloating(Integer.parseInt(floatingString));
						card.setControls(controlList);
						newCards.add(card);
					}

					cards = newCards;

				} else {
					return "Set not found";
				}
			} else {
				return "Wrong version";
			}
		} catch (Exception e) { //DOMParseException
			return e.getMessage();
		}				

		return null;
	}	

	private void setCards(List<Card> cards) {

		this.cards = cards; 

		StringBuffer text = new StringBuffer();
		text.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n");
		text.append("<atomyq version=\"3\">\n\n");
		text.append("<set>");
		for (int i=0, n=cards.size(); i<n; ++i) {
			final Card card = cards.get(i);
			text.append("\n\n"+card.getXML(""+i).toString());
		}		
		text.append("\n\n</set>");
		text.append("\n\n</atomyq>");
		source.setValue(text.toString());
	}

	@Override
	public boolean isSafeToClose() {
		return isSafeToClose;
	}

	@Override
	public List<Card> getCards() {
		return cards;
	}
}
